package org.jeecg.modules.basesource.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.xxl.job.core.util.ShardingUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.modules.basesource.entity.CwbbSyncRecord;
import org.jeecg.modules.dzswj.exception.SmdlException;
import org.jeecg.modules.basesource.service.ICwbbSyncRecordService;
import org.jeecg.modules.basesource.service.ISbCwbbService;
import org.jeecg.modules.dzswj.GuangdongSfjrApiService;
import org.jeecg.modules.dzswj.vo.LoginSessionVo;
import org.jeecg.modules.dzswj.vo.request.CwbbReqVo;
import org.jeecg.modules.dzswj.vo.response.cwbb.GsCwbbVo;
import org.jeecg.modules.qyxx.entity.CjQyxxStatus;
import org.jeecg.modules.qyxx.entity.DjNsrxxPO;
import org.jeecg.modules.qyxx.service.ICjQyxxStatusService;
import org.jeecg.modules.qyxx.service.IDjNsrxxService;
import org.jeecg.modules.qyxx.util.DateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.*;

/**
 * 财报数据采集任务调度
 * @author chensherun on 2022/3/8.
 * @version 1.0
 */
@Slf4j
@Component
public class CwbbCjHandler {

    @Autowired
    private ICjQyxxStatusService cjQyxxStatusService;

    @Autowired
    private GuangdongSfjrApiService sfjrApiService;

    @Autowired
    private IDjNsrxxService djNsrxxService;

    @Autowired
    private ISbCwbbService cwbbService;

    @Autowired
    private ICwbbSyncRecordService cwbbSyncRecordService;

    private static ExecutorService executor = new ThreadPoolExecutor(5, 10, 0L,
            TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(10000),
            new ThreadPoolExecutor.CallerRunsPolicy());

    /**
     * 采集季度数据
     * @param
     * @return
     */
    @XxlJob(value = "cjCwbbJbJob")
    public ReturnT<String> cjCwbbJbJob(String param) {
        ShardingUtil.ShardingVO shardingVO = ShardingUtil.getShardingVo();
        if (shardingVO == null) {
            shardingVO = new ShardingUtil.ShardingVO(0, 1);
        }
        String tynsrsbh = null;
        JSONObject jsonObject = JSONObject.parseObject(param);
        if (jsonObject != null) {
            tynsrsbh = jsonObject.getString("tynsrsbh");
        }
        List<Future> futureList = new ArrayList<>();
        LambdaQueryWrapper<CjQyxxStatus> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CjQyxxStatus::getType, "02").eq(CjQyxxStatus::getStatus, "0");
        if (StringUtils.isNotBlank(tynsrsbh)) {
            queryWrapper.eq(CjQyxxStatus::getNsrsbh, tynsrsbh);
        }
        List<CjQyxxStatus> list = cjQyxxStatusService.list(queryWrapper);
        DateUtils dateUtils = DateUtils.getInstance();
        //获取当前要采集的起止时间获取
        for (CjQyxxStatus cjQyxxStatus : list) {
            futureList.add(executor.submit(new Callable() {
                @Override
                public Object call() throws Exception {
                    log.info("开始同步企业{}，开始时间：{}， 结束时间: {}", cjQyxxStatus.getDjxh(),
                            DateUtils.getInstance().format(cjQyxxStatus.getKssj()),
                            DateUtils.getInstance().format(cjQyxxStatus.getJssj()));
                    long start = System.currentTimeMillis();
                    String cjTynsrsbh = cjQyxxStatus.getDjxh();
                    DjNsrxxPO djNsrxx = djNsrxxService.getById(cjQyxxStatus.getDjxh());
                    //判断起止时间超过1年，则全量，否则是增量
                    Date kssj = cjQyxxStatus.getKssj();
                    Calendar kssjCal = Calendar.getInstance();
                    kssjCal.setTime(kssj);
                    Date jssj = cjQyxxStatus.getJssj();
                    Calendar jssjCal = Calendar.getInstance();
                    jssjCal.setTime(jssj);
                    int months = dateUtils.getCountBeforeTwoTime(kssj, jssj);
                    boolean isAllSuccess = true;
                    //首次，全量
                    if (months >= 12 && kssjCal.get(Calendar.MONTH) == 0 && kssjCal.get(Calendar.DATE) == 1) {
                        //结束时间再往前推一个月份，1月份申报12月份的，2月份才能取数。
                        //2月份取数时，数据是xxxx-01-01 至 xxxx-01-31
                        //3月份取数时，数据是xxxx-02-01 至 xxxx-02-28
                        //所以属期最大也要是当前月份再往前两个月，这里需要再减一个月
                        jssjCal.add(Calendar.MONTH, -1);
                        Calendar endCalendar = Calendar.getInstance();
                        endCalendar.setTime(dateUtils.getCurrentQuarterStartTime(jssjCal.getTime()));

                        //全量
                        do {
                            String ssqq = dateUtils.format(dateUtils.getCurrentQuarterStartTime(kssjCal.getTime()));
                            String ssqz = dateUtils.format(dateUtils.getCurrentQuarterEndTime(kssjCal.getTime()));
                            CwbbReqVo cwbbReqVo = new CwbbReqVo();
                            cwbbReqVo.setDjxh(djNsrxx.getDjxh());
                            cwbbReqVo.setSsqq(ssqq);
                            cwbbReqVo.setSsqz(ssqz);

                            CwbbSyncRecord cwbbSyncRecord = cwbbSyncRecordService.getByDjxhSsq(djNsrxx.getDjxh(), ssqq, ssqz);
                            if (cwbbSyncRecord == null) {
                                cwbbSyncRecord = new CwbbSyncRecord();
                                BeanUtils.copyProperties(cwbbReqVo, cwbbSyncRecord);
                            }
                            cwbbSyncRecord.setNsrsbh(cjTynsrsbh);
                            try {
                                LoginSessionVo loginInfo = sfjrApiService.getNsrLoginSessionInfo(cjTynsrsbh);
                                GsCwbbVo cwbb = sfjrApiService.cwbb(loginInfo.getSessionId(), loginInfo.getZgswjdm(), cwbbReqVo);
                                if (cwbb == null) {
                                    cwbbSyncRecord.setStatus("200");
                                } else {
                                    cwbbService.saveJbCwbb(cjTynsrsbh, djNsrxx.getNsrmc(), ssqq, ssqz, cwbb);
                                    cwbbSyncRecord.setStatus("100");
                                }
                                cwbbSyncRecord.setRemark("成功");
                            } catch (Exception e) {
                                log.error("调用财报接口错误,", e);
                                String errorMsg = e.getMessage();
                                if (e instanceof SmdlException) {
                                    cwbbSyncRecord.setStatus("-2");
                                    errorMsg = "【" + ((SmdlException) e).getErrorCode().getCode() + "】"+ e.getMessage();
                                } else {
                                    cwbbSyncRecord.setStatus("-1");
                                }
                                cwbbSyncRecord.setRemark(errorMsg + ", 入参:" + JSON.toJSONString(cwbbReqVo));
                                //同步出错
                                isAllSuccess = false;
                            }
                            cwbbSyncRecordService.saveOrUpdate(cwbbSyncRecord);
                            //加3个月
                            kssjCal.add(Calendar.MONTH, 3);
                        } while(kssjCal.before(endCalendar));
                    } else {
                        //增量数据要计算要同步哪个时间段。
                        //4,7,10,1月份分别同步上季度数据，其他月份不同步。
                        int month = jssjCal.get(Calendar.MONTH) + 1;
                        List<Integer> syncMonth = Arrays.asList(1, 4, 7, 10);
                        if (!syncMonth.contains(month)) {
                            cjQyxxStatus.setStatus("1");
                        } else {
                            jssjCal.add(Calendar.MONTH, -1);
                            String ssqq = dateUtils.format(dateUtils.getCurrentQuarterStartTime(jssjCal.getTime()));
                            String ssqz = dateUtils.format(dateUtils.getCurrentQuarterEndTime(jssjCal.getTime()));
                            CwbbReqVo cwbbReqVo = new CwbbReqVo();
                            cwbbReqVo.setDjxh(djNsrxx.getDjxh());
                            cwbbReqVo.setSsqq(ssqq);
                            cwbbReqVo.setSsqz(ssqz);
                            CwbbSyncRecord cwbbSyncRecord = cwbbSyncRecordService.getByDjxhSsq(djNsrxx.getDjxh(), ssqq, ssqz);
                            if (cwbbSyncRecord == null) {
                                cwbbSyncRecord = new CwbbSyncRecord();
                                BeanUtils.copyProperties(cwbbReqVo, cwbbSyncRecord);
                            }
                            cwbbSyncRecord.setNsrsbh(cjTynsrsbh);
                            try {
                                LoginSessionVo loginInfo = sfjrApiService.getNsrLoginSessionInfo(cjTynsrsbh);
                                GsCwbbVo cwbb = sfjrApiService.cwbb(loginInfo.getSessionId(), loginInfo.getZgswjdm(), cwbbReqVo);
                                if (cwbb == null) {
                                    cwbbSyncRecord.setStatus("200");
                                } else {
                                    cwbbService.saveJbCwbb(cjTynsrsbh, djNsrxx.getNsrmc(), ssqq, ssqz, cwbb);
                                    cwbbSyncRecord.setStatus("100");
                                }
                                cwbbSyncRecord.setRemark("成功");
                            } catch (Exception e) {
                                log.error("调用财报接口错误,", e);
                                String errorMsg = e.getMessage();
                                if (e instanceof SmdlException) {
                                    cwbbSyncRecord.setStatus("-2");
                                    errorMsg = "【" + ((SmdlException) e).getErrorCode().getCode() + "】"+ e.getMessage();
                                } else {
                                    cwbbSyncRecord.setStatus("-1");
                                }
                                cwbbSyncRecord.setRemark(errorMsg + ", 入参:" + JSON.toJSONString(cwbbReqVo));
                                //同步出错
                                isAllSuccess = false;
                            }
                            cwbbSyncRecordService.saveOrUpdate(cwbbSyncRecord);
                        }
                    }

                    if (isAllSuccess) {
                        cjQyxxStatus.setStatus("1");
                    }
                    //更新记录
                    cjQyxxStatusService.updateByMultiId(cjQyxxStatus);

                    long time = (System.currentTimeMillis() - start) / 1000;
                    log.info("结束同步企业{}，时间范围起：{}， 时间范围止: {}，耗时: {}", cjQyxxStatus.getDjxh(),
                            DateUtils.getInstance().format(cjQyxxStatus.getKssj()),
                            DateUtils.getInstance().format(cjQyxxStatus.getJssj()), time);
                    return null;
                }
            }));
        }
        for (Future f : futureList) {
            try {
                f.get();
            } catch (Exception e) {
                log.error("同步财报数据失败," + e.getMessage());
            }
        }
        return ReturnT.SUCCESS;
    }

    public static void main(String[] args) {
        DateUtils dateUtils = DateUtils.getInstance();
//        CwbbSyncRecord cwbbSyncRecord = new CwbbSyncRecord();
//        Calendar kssjCal = Calendar.getInstance();
//        String ssqq = dateUtils.format(dateUtils.getCurrentQuarterStartTime(kssjCal.getTime()));
//        String ssqz = dateUtils.format(dateUtils.getCurrentQuarterEndTime(kssjCal.getTime()));
//
//
//        Calendar cal = Calendar.getInstance();
//        int year = cal.get(Calendar.YEAR);
//        int month = cal.get(Calendar.MONTH);
//        cal.set(year, month - 1, 1, 00, 00, 00);
//        Date first = cal.getTime();
//        cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DATE));
//        Date last = cal.getTime();
//        System.out.println(first);
//        System.out.println(last);

        Calendar kssjCal = Calendar.getInstance();
        Calendar jssjCal = Calendar.getInstance();
        String date20180101 = dateUtils.getFirstDayOfMonth(2018, 1);
        String date20220208 = dateUtils.getLastDayOfMonth(2022, 2);
        kssjCal.setTime(dateUtils.strToDate(date20180101, "yyyy-MM-dd"));
        jssjCal.setTime(dateUtils.strToDate(date20220208, "yyyy-MM-dd"));
        jssjCal.add(Calendar.MONTH, -1);
        Calendar endCalendar = Calendar.getInstance();
        endCalendar.setTime(dateUtils.getCurrentQuarterStartTime(jssjCal.getTime()));
        int i = 0;
        do {
            System.out.println(++i);
            String ssqq = dateUtils.format(dateUtils.getCurrentQuarterStartTime(kssjCal.getTime()));
            String ssqz = dateUtils.format(dateUtils.getCurrentQuarterEndTime(kssjCal.getTime()));
            System.out.println(ssqq + ", " + ssqz);
            kssjCal.add(Calendar.MONTH, 3);
        } while (kssjCal.before(endCalendar));
    }
}
